package snail.tiger.com.tigerplayer.views;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

import snail.tiger.com.tigerplayer.R;
import snail.tiger.com.tigerplayer.tools.SharedPreferencesUtils;
import snail.tiger.com.tigerplayer.tools.AudioPlayerUtil;
import snail.tiger.com.tigerplayer.tools.Tools;
import snail.tiger.com.tigerplayer.users.User;
import snail.tiger.com.tigerplayer.callbacks.BetsChangeCallback;

public class TigerView extends LinearLayout implements View.OnClickListener {

    private Context mContext;

    /**
     * 老虎机状态
     */
    public int status = User.EMPTY_STATE;

    public int getStatus() {
        return status;
    }

    public TigerView(Context context) {
        super(context);
        init(context);
    }

    public TigerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public TigerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        this.mContext = context;

        View view = View.inflate(context, R.layout.tiger_view, this);

        // 得分布局
        View scoreTable = view.findViewById(R.id.layout_score_table);
        initScoreTable(scoreTable);

        // 启动-退币等按钮布局
        View ctrlTable = view.findViewById(R.id.layout_ctrl_table);
        initCtrlTable(ctrlTable);

        // 下注布局
        View betsTable = view.findViewById(R.id.layout_bets_table);
        initBetsTable(betsTable);

        // 转盘布局
        View turnTable = view.findViewById(R.id.layout_turn_table);
        initTurnTable(turnTable);
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        switch (id) {
            case R.id.start:
                start();
                break;
            case R.id.exit:
                if (status == User.RUNNING_STATE) {
                    return;
                }
                AudioPlayerUtil.getInstance().playSound(15, 1);

                exitScore();// 先计算分数，并退回
                refreshBetsView();// 刷新赔率，并将下注额归0
                mStartView.setText("启动");
                break;
        }
    }

    //======================================计分布局======================================//

    /**
     * 计分和得分
     */
    private TextView mTxtScore;
    private TextView mTxtRewardScore;

    /**
     * 得分
     */
    private int mResultScore;

    /**
     * 初始化得分布局
     */
    private void initScoreTable(View scoreTable) {
        mTxtScore = scoreTable.findViewById(R.id.score);
        mTxtRewardScore = scoreTable.findViewById(R.id.reward_score);

        showScore();
    }

    public void showScore() {
        mTxtScore.setText(String.valueOf(User.SCORE));
        mTxtRewardScore.setText(String.valueOf(mResultScore));
    }

    //======================================控制布局======================================//

    private TextView mStartView;

    /**
     * 初始化控制布局
     */
    private void initCtrlTable(View ctrlTable) {
        TextView mExitView = ctrlTable.findViewById(R.id.exit);
        mExitView.setOnClickListener(this);

        mStartView = ctrlTable.findViewById(R.id.start);
        mStartView.setOnClickListener(this);
    }

    /**
     * 计算当前下注额并退分
     */
    private void exitScore() {
        int size = mBetsViews.size();
        for (int i = 0; i < size; i++) {
            User.SCORE += mBetsViews.get(i).getBetsNum();
        }

        showScore();
    }

    //======================================下注布局======================================//

    /**
     * 下注控件的集合
     */
    private List<BetsView> mBetsViews;
    private List<BetsView> mRedBetsViews;
    private List<BetsView> mGreenBetsViews;
    private List<BetsView> mYellowBetsViews;

    /**
     * 五种赔率数组
     */
    private Integer[] oddsOne = new Integer[]{47, 23, 13, 8};
    private Integer[] oddsTwo = new Integer[]{40, 20, 11, 7};
    private Integer[] oddsThree = new Integer[]{35, 17, 10, 6};
    private Integer[] oddsFour = new Integer[]{31, 15, 9, 5};
    private Integer[] oddsFive = new Integer[]{28, 14, 7, 4};

    /**
     * 初始化下注布局
     */
    private void initBetsTable(View betsTable) {
        // 红色控件的集合
        mRedBetsViews = new ArrayList<>();
        BetsView betRedBenz = betsTable.findViewById(R.id.bet_red_Benz);
        BetsView betRedBMW = betsTable.findViewById(R.id.bet_red_BMW);
        BetsView betRedAudi = betsTable.findViewById(R.id.bet_red_Audi);
        BetsView betRedJetta = betsTable.findViewById(R.id.bet_red_Jetta);
        mRedBetsViews.add(betRedBenz);
        mRedBetsViews.add(betRedBMW);
        mRedBetsViews.add(betRedAudi);
        mRedBetsViews.add(betRedJetta);

        // 绿色控件的集合
        mGreenBetsViews = new ArrayList<>();
        BetsView betGreenBenz = betsTable.findViewById(R.id.bet_green_Benz);
        BetsView betGreenBMW = betsTable.findViewById(R.id.bet_green_BMW);
        BetsView betGreenAudi = betsTable.findViewById(R.id.bet_green_Audi);
        BetsView betGreenJetta = betsTable.findViewById(R.id.bet_green_Jetta);
        mGreenBetsViews.add(betGreenBenz);
        mGreenBetsViews.add(betGreenBMW);
        mGreenBetsViews.add(betGreenAudi);
        mGreenBetsViews.add(betGreenJetta);

        // 蓝色控件的集合
        mYellowBetsViews = new ArrayList<>();
        BetsView betYellowBenz = betsTable.findViewById(R.id.bet_yellow_Benz);
        BetsView betYellowBMW = betsTable.findViewById(R.id.bet_yellow_BMW);
        BetsView betYellowAudi = betsTable.findViewById(R.id.bet_yellow_Audi);
        BetsView betYellowJetta = betsTable.findViewById(R.id.bet_yellow_Jetta);
        mYellowBetsViews.add(betYellowBenz);
        mYellowBetsViews.add(betYellowBMW);
        mYellowBetsViews.add(betYellowAudi);
        mYellowBetsViews.add(betYellowJetta);

        // 下注控件的集合
        mBetsViews = new ArrayList<>();
        mBetsViews.addAll(mRedBetsViews);
        mBetsViews.addAll(mGreenBetsViews);
        mBetsViews.addAll(mYellowBetsViews);

        int size = mBetsViews.size();
        for (int i = 0; i < size; i++) {
            mBetsViews.get(i).setBetsChangeCallback(new BetsChangeCallback() {
                @Override
                public void onBetsChangeCallback() {
                    status = User.READY_STATE;
                    mStartView.setText("启动");
                    showScore();
                }
            });
        }

        refreshBetsView();
    }

    /**
     * 刷新所有下注控件（刷新赔率，并将下注额归0）
     * 将五种赔率随机取三个，随机分给三种颜色
     */
    private void refreshBetsView() {
        List<Integer[]> allOdds = new ArrayList<>();
        allOdds.add(oddsOne);
        allOdds.add(oddsTwo);
        allOdds.add(oddsThree);
        allOdds.add(oddsFour);
        allOdds.add(oddsFive);

        // 红色赔率
        int randomNumRed = Tools.getRandomNum(0, 4);
        Integer[] redOdds = allOdds.get(randomNumRed);
        allOdds.remove(randomNumRed);

        // 绿色赔率
        int randomNumGreen = Tools.getRandomNum(0, 3);
        Integer[] greenOdds = allOdds.get(randomNumGreen);
        allOdds.remove(randomNumGreen);

        // 黄色赔率
        int randomNumYellow = Tools.getRandomNum(0, 2);
        Integer[] yellowOdds = allOdds.get(randomNumYellow);
        allOdds.remove(randomNumYellow);

        // 给红绿黄初始化赔率和下注额
        initBetsViewsOddAndNum(mRedBetsViews, redOdds);
        initBetsViewsOddAndNum(mGreenBetsViews, greenOdds);
        initBetsViewsOddAndNum(mYellowBetsViews, yellowOdds);
    }

    /**
     * 给红绿黄初始化赔率和下注额
     */
    private void initBetsViewsOddAndNum(List<BetsView> betsViews, Integer[] odds) {
        for (int i = 0; i < 4; i++) {
            betsViews.get(i).setBetsNum(0);
            betsViews.get(i).setBetsOdds(odds[i]);
        }
    }

    //======================================转盘布局======================================//
    /**
     * 转盘上所有控件
     */
    private List<TurnView> mTurnViews;

    /**
     * 初始化转盘布局
     */
    private void initTurnTable(View turnTable) {
        mTurnViews = new ArrayList<>();

        TurnView mRedBenzTop = turnTable.findViewById(R.id.red_Benz_top);
        TurnView mRedBenzBottom = turnTable.findViewById(R.id.red_Benz_bottom);
        TurnView mGreenBenzTop = turnTable.findViewById(R.id.green_Benz_top);
        TurnView mGreenBenzBottom = turnTable.findViewById(R.id.green_Benz_bottom);
        TurnView mYellowBenzTop = turnTable.findViewById(R.id.yellow_Benz_top);
        TurnView mYellowBenzBottom = turnTable.findViewById(R.id.yellow_Benz_bottom);

        TurnView mRedBMWTop = turnTable.findViewById(R.id.red_BMW_top);
        TurnView mRedBMWBottom = turnTable.findViewById(R.id.red_BMW_bottom);
        TurnView mGreenBMWTop = turnTable.findViewById(R.id.green_BMW_top);
        TurnView mGreenBMWBottom = turnTable.findViewById(R.id.green_BMW_bottom);
        TurnView mYellowBMWTop = turnTable.findViewById(R.id.yellow_BMW_top);
        TurnView mYellowBMWBottom = turnTable.findViewById(R.id.yellow_BMW_bottom);

        TurnView mRedAudiTop = turnTable.findViewById(R.id.red_Audi_top);
        TurnView mRedAudiBottom = turnTable.findViewById(R.id.red_Audi_bottom);
        TurnView mGreenAudiTop = turnTable.findViewById(R.id.green_Audi_top);
        TurnView mGreenAudiBottom = turnTable.findViewById(R.id.green_Audi_bottom);
        TurnView mYellowAudiTop = turnTable.findViewById(R.id.yellow_Audi_top);
        TurnView mYellowAudiBottom = turnTable.findViewById(R.id.yellow_Audi_bottom);

        TurnView mRedJettaLeft = turnTable.findViewById(R.id.red_Jetta_left);
        TurnView mRedJettaRight = turnTable.findViewById(R.id.red_Jetta_right);
        TurnView mGreenJettaLeft = turnTable.findViewById(R.id.green_Jetta_left);
        TurnView mGreenJettaRight = turnTable.findViewById(R.id.green_Jetta_right);
        TurnView mYellowJettaLeft = turnTable.findViewById(R.id.yellow_Jetta_left);
        TurnView mYellowJettaRight = turnTable.findViewById(R.id.yellow_Jetta_right);
        mTurnViews.add(mRedBenzTop);
        mTurnViews.add(mYellowJettaRight);
        mTurnViews.add(mGreenJettaRight);
        mTurnViews.add(mRedJettaRight);
        mTurnViews.add(mYellowAudiBottom);
        mTurnViews.add(mGreenAudiBottom);
        mTurnViews.add(mRedAudiBottom);
        mTurnViews.add(mYellowBMWBottom);
        mTurnViews.add(mGreenBMWBottom);
        mTurnViews.add(mRedBMWBottom);
        mTurnViews.add(mYellowBenzBottom);
        mTurnViews.add(mGreenBenzBottom);
        mTurnViews.add(mRedBenzBottom);
        mTurnViews.add(mYellowJettaLeft);
        mTurnViews.add(mGreenJettaLeft);
        mTurnViews.add(mRedJettaLeft);
        mTurnViews.add(mYellowAudiTop);
        mTurnViews.add(mGreenAudiTop);
        mTurnViews.add(mRedAudiTop);
        mTurnViews.add(mYellowBMWTop);
        mTurnViews.add(mGreenBMWTop);
        mTurnViews.add(mRedBMWTop);
        mTurnViews.add(mYellowBenzTop);
        mTurnViews.add(mGreenBenzTop);
    }

    /**
     * 当前位置
     */
    private int currentIndex = 0;
    private int preIndex = 0;

    /**
     * 启动按钮
     * 运行状态与得分状态都直接返回
     */
    private void start() {
        switch (status) {
            case User.EMPTY_STATE:
                return;
            case User.READY_STATE:
                newBets();
                break;
            case User.RUNNING_STATE:
                return;
            case User.STOP_STATE:
                break;
            case User.GET_RESULT_STATE:
                User.SCORE += mResultScore;// 点击启动，将得分收回到总分
                mResultScore = 0;// 得分归零
                showScore();// 显示计分
                refreshBetsView();// 刷新BetsViews
                mStartView.setText("续押");
                status = User.END_STATE;
                return;
            case User.END_STATE:
                if (isCanGoOn()) {
                    continueBets();
                } else {
                    Toast.makeText(mContext, "兄弟，你的钱不够了", Toast.LENGTH_SHORT).show();
                    return;
                }
                break;
        }

        status = User.RUNNING_STATE;

        // 启动!!!
        tryStopIndex(mChanceItem[randomItem()]);
        new Thread(new Runnable() {
            @Override
            public void run() {
                User.IsRunning = true;
                while (status == User.RUNNING_STATE) {
                    try {
                        mHandler.sendEmptyMessage(88);
                        Thread.sleep(getInterceptTime());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    // 到达了指定位置 && 速度足够慢 && 跑了三圈 就可以停下来了
                    if ((currentIndex == mStopIndex1
//                       || currentIndex == mStopIndex2
//                        || currentIndex == mStopIndex4
                            || currentIndex == mStopIndex3)
                            && currentTotal >= 48
                            && currentTime >= 300) {
                        // 运行状态停止
                        status = User.STOP_STATE;
                        User.IsRunning = false;
                    }
                }
                mHandler.sendEmptyMessage(99);
            }
        }).start();
    }

    /**
     * 当前停留时间
     * 最小停留时间
     */
    private int currentTime = MAX_TIME;//这个值越大，表示停留时间越长，速度越慢
    private static int MIN_TIME = 50;
    private static int MAX_TIME = 500;

    /**
     * 当前经过总的位置
     */
    private int currentTotal = 1;

    /**
     * 获取停顿时间
     * 停顿时间是由长变短，再由短变长，所以需要一个速度最大值与最小值
     */
    private int getInterceptTime() {
        currentTotal++;

        if (currentTotal <= 48) {
            currentTime -= 50;
            if (currentTime <= MIN_TIME) {
                currentTime = MIN_TIME;
            }
        } else {
            currentTime += 25;
            if (currentTime >= MAX_TIME) {
                currentTime = MAX_TIME;
            }
        }

        return currentTime;
    }

    /**
     * 下车点(因为是对称，所以+12也行)
     */
    private int mStopIndex1 = 0;
    //    private int mStopIndex2 = 6;
    private int mStopIndex3 = 12;
//    private int mStopIndex4 = 18;

    /**
     * 指定下车点（不然怎么叫老虎机）
     */
    private void tryStopIndex(int stopIndex) {
        mStopIndex1 = stopIndex % 24;
//        mStopIndex2 = (stopIndex + 6) % 24;
        mStopIndex3 = (stopIndex + 12) % 24;
//        mStopIndex4 = (stopIndex + 18) % 24;
    }

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            int what = msg.what;

            if (what == 88) {
                preIndex = currentIndex;
                currentIndex++;
                if (currentIndex == 24) {
                    currentIndex = 0;
                }
                mTurnViews.get(preIndex).setFocus(false);
                mTurnViews.get(currentIndex).setFocus(true);
            } else if (what == 99) {
                //清算
                countResult();
            }
        }
    };

    /**
     * 结算
     */
    private void countResult() {
        // 清空handler中的消息，防止内存溢出
        mHandler.removeCallbacksAndMessages(null);

        currentTime = MAX_TIME;// 速度还原
        currentTotal = 0;// 轮盘计数变量归零

        // 下注额和赔率
        int betsNum = 0;
        int betsOdds = 0;

        // 需要播放的音效
        int musicNum = 0;

        switch (currentIndex) {
            case 0:
            case 12:
                betsNum = mRedBetsViews.get(0).getBetsNum();
                betsOdds = mRedBetsViews.get(0).getBetsOdds();
                musicNum = 1;
                break;
            case 1:
            case 13:
                betsNum = mYellowBetsViews.get(3).getBetsNum();
                betsOdds = mYellowBetsViews.get(3).getBetsOdds();
                musicNum = 12;
                break;
            case 2:
            case 14:
                betsNum = mGreenBetsViews.get(3).getBetsNum();
                betsOdds = mGreenBetsViews.get(3).getBetsOdds();
                musicNum = 11;
                break;
            case 3:
            case 15:
                betsNum = mRedBetsViews.get(3).getBetsNum();
                betsOdds = mRedBetsViews.get(3).getBetsOdds();
                musicNum = 10;
                break;
            case 4:
            case 16:
                betsNum = mYellowBetsViews.get(2).getBetsNum();
                betsOdds = mYellowBetsViews.get(2).getBetsOdds();
                musicNum = 9;
                break;
            case 5:
            case 17:
                betsNum = mGreenBetsViews.get(2).getBetsNum();
                betsOdds = mGreenBetsViews.get(2).getBetsOdds();
                musicNum = 8;
                break;
            case 6:
            case 18:
                betsNum = mRedBetsViews.get(2).getBetsNum();
                betsOdds = mRedBetsViews.get(2).getBetsOdds();
                musicNum = 7;
                break;
            case 7:
            case 19:
                betsNum = mYellowBetsViews.get(1).getBetsNum();
                betsOdds = mYellowBetsViews.get(1).getBetsOdds();
                musicNum = 6;
                break;
            case 8:
            case 20:
                betsNum = mGreenBetsViews.get(1).getBetsNum();
                betsOdds = mGreenBetsViews.get(1).getBetsOdds();
                musicNum = 5;
                break;
            case 9:
            case 21:
                betsNum = mRedBetsViews.get(1).getBetsNum();
                betsOdds = mRedBetsViews.get(1).getBetsOdds();
                musicNum = 4;
                break;
            case 10:
            case 22:
                betsNum = mYellowBetsViews.get(0).getBetsNum();
                betsOdds = mYellowBetsViews.get(0).getBetsOdds();
                musicNum = 3;
                break;
            case 11:
            case 23:
                betsNum = mGreenBetsViews.get(0).getBetsNum();
                betsOdds = mGreenBetsViews.get(0).getBetsOdds();
                musicNum = 2;
                break;
        }

        // 播放
        AudioPlayerUtil.getInstance().playSound(musicNum, 1);

        // 一次游戏结束，记录下注额
        rememberBets();

        mResultScore = betsNum * betsOdds;
        if (mResultScore != 0) {
            status = User.GET_RESULT_STATE;
            mTxtRewardScore.setText(String.valueOf(mResultScore));
            mStartView.setText("汇总");// 显示汇总是为了将分转移过来
        } else {
            status = User.END_STATE;
            // 没中的话就刷新
            refreshBetsView();
            mStartView.setText("续押");
        }

        SharedPreferencesUtils.commitInt("userScore", User.SCORE + mResultScore);
    }

    //======================================续押用到的方法======================================//

    /**
     * 新押（重新下注之后，清除掉所有续押记录）
     */
    private void newBets() {
        int size = mBetsViews.size();
        for (int i = 0; i < size; i++) {
            mBetsViews.get(i).newBet();
        }
    }

    /**
     * 续押
     */
    private void continueBets() {
        int size = mBetsViews.size();
        for (int i = 0; i < size; i++) {
            mBetsViews.get(i).continueBet();
        }
        showScore();
    }

    /**
     * 记录下注，为了下次可以续押
     */
    private void rememberBets() {
        int size = mBetsViews.size();
        for (int i = 0; i < size; i++) {
            mBetsViews.get(i).rememberBet();
        }
    }

    /**
     * 此处判断总分是否够续押
     */
    private boolean isCanGoOn() {
        int ret = 0;

        int size = mBetsViews.size();
        for (int i = 0; i < size; i++) {
            // 这里BetsNum已经被清为0了，所以只能读续押的记录值(按逻辑也是读这个值)
            ret += mBetsViews.get(i).getCacheBetsNum();
        }

        return ret <= User.SCORE;
    }

    //======================================随机方法======================================//
    /**
     * 权重设置出现概率
     * 奔驰10%
     * 宝马20%
     * 奥迪30%
     * 捷达40%
     */
    private Integer[] mChanceItem = new Integer[]{
            0, 23, 22, 12, 10, 11,// 奔驰
            21, 21, 20, 20, 19, 19, 9, 9, 8, 8, 7, 7,//宝马
            18, 18, 18, 17, 17, 17, 16, 16, 16, 4, 4, 4, 5, 5, 5, 6, 6, 6,//奥迪
            15, 15, 15, 15, 14, 14, 14, 14, 13, 13, 13, 13, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3//捷达
    };

    private int randomItem() {
        return Tools.getRandomNum(0, mChanceItem.length - 1);
    }
}
